const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
// 设置nodejs环境变量 注释掉就默认走production了，和webpack.config.js的mode属性无关
// process.env.NODE_ENV='development';
module.exports = {
    entry: ['./src/index.js', './src/index.html'],
    output: {
        filename: 'daBaoHou.contenthash[6].js',
        path: resolve(__dirname, 'build')
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                // 一定要排除掉node_modules
                exclude: /node_modules/,
                // 优先执行这个，再执行下面匹配到的Loader。比如js先匹配了这个，然后再去oneOf数组里面找一个匹配。也就是能匹配两个
                enfore: 'pre',
                loader: 'eslint-loader',
                options: {
                    // 为false的话就需要自己手动校准
                    // 是否自动校准，这里面的自动校准就是eslint语法校准
                    fix: true
                }
            },
            {
                // 以下loader只能匹配一个。比如js如果能匹配两个loader，但是他还是会只走其中的一个
                oneOf: [
                    {
                        test: /\.js$/,
                        exclude: /node_modules/,
                        loader: 'babel-loader',
                        options: {
                            // 指示babel要做什么样的兼容性处理
                            presets: [
                                ['@babel/preset-env',
                                    {
                                        // 按需加载
                                        useBuiltIns: 'usage',
                                        // 指定core-js版本
                                        corejs: {
                                            version: 3
                                        },
                                        // 指定兼容性做到哪个版本的浏览器
                                        targets: {
                                            chrome: '60',
                                            firefox: '60',
                                            ie: '9',
                                            safari: '10',
                                            edge: '17'
                                        }
                                    }]
                            ],
                            // 是否开启babel缓存 第二次构建时候，会读取之前的缓存从而提高速度
                            cacheDirectory: true,
                        }
                    }, {
                        test: /\.css$/,
                        use: [
                            // 'style-loader', 
                            // 这个loader替代style-loader。作用：把js中的css打包成为单独的文件
                            MiniCssExtractPlugin.loader,
                            'css-loader',
                            {
                                loader: 'postcss-loader',
                                // 在postcss.config.js写了配置，所以option里面注释掉了
                                /* options:{
                                    ident:'postcss',
                                    plugins:()=>[require('postcss-preset'-env)()]
                                } */
                            }
                        ],
                    }, {
                        test: /\.less$/,
                        // 使用哪些loader
                        // 使用这些loader前我们一般都会在项目最外层下载这些依赖。因为npm会一层一层往上面找。所以我们就放在最外面一层 npm i webpack webpack-cli -D
                        // npm i css-loader style-loader -D
                        use: [
                            //use数组中loader执行的顺序：从右到左，从上到下，依次执行
                            // 创建了style标签，将js中的样式资源插入进行，添加到head中
                            'style-loader',
                            // 将css文件编译成commonjs模块加载到js中，里面内容是样式字符串
                            'css-loader',
                            'less-loader'
                        ]
                    }, {
                        test: /\.(jpg|png|gif)$/,
                        // 下载url-loader file-loader
                        loader: 'url-loader',
                        options: {
                            // 图片大小小于8kb就会被base64处理
                            // 优点：减少请求数量，减轻服务器压力
                            // 缺点：图片体积会更大（文件请求速度更慢）
                            limit: 8 * 1024,
                            // 遇到的bug:url-loader默认用es6模块化解析，而html-loader引入图片是commonjs引入
                            // 解析时候Img src就是引入了[Object module]
                            // 解决方法关闭url-loader的es6模块化，使用commonjs解析
                            esModule: false,
                            // 给图片的哈希名字进行压缩
                            name: '[hash:10].[ext]'
                        }
                    }, {
                        test: /\.html$/,
                        // 处理html文件的img图片（负责引入img，从而能够被url-loader解析处理
                        loader: 'html-loader'
                    }, {
                        // 我们不单单可以用test也可以用exclude排除哪些文件
                        //{ test: /\.css$/, loader: 'style!css' },其他写法1、"-loader"其实是可以省略不写的，多个loader之间用“!”连接起来。
                        exclude: /\.(css|js|html|less|jpg|png|gif)/, loader: 'file-loader', options: { name: '[hash:10].[ext]' }
                    }]
            }]
    },
    plugins: [new HtmlWebpackPlugin({
        // 默认就会引入打包后的js文件
        // 决定了模仿哪个页面结构
        template: './src/index.html',
        minify: {
            // 是否移除空格
            collapseWhitespace: true,
            // 是否移除注释
            removeComments: true
        }
    }),
    new MiniCssExtractPlugin({
        // 对输出的css文件重命名
        filename: 'css/built.[contenthash:10].css'
    }),
    new OptimizeCssAssetsWebpackPlugin()],
    mode: 'development',
    // 特点：只会在内存中编译打包。不会有任何输出
    // 启动devServer指令：npx webpack-dev-server
    devServer: {
        contentBase: resolve(__dirname, 'build'),
        // 启用gzip压缩
        // comporess: true,
        // 端口号
        port: 10,
        // 是否开启HMR功能 
        // 新配置如果想要生效，必须要重启webpack服务
        hot: true
    },
    devtool: 'eval-source-map'
    /* source-map 默认值 外部，错误代码准确信息 和 源代码的错误的位置
    [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
    注意了哦，顺序关系一定不可以写错！
    inline-source-map 内联格式，不会生成额外的source-map文件，而是直接写在打包后的js文件的最底部。错误代码准确信息和源代码错误位置
    hidden-source-map 外部格式 生成一个额外的source-map js文件 错误代码错误原因，但是没有错误位置。不能追踪源代码错误，只能提示到构建后代码的错误位置（所以这个用的就比较少，实用性低）
    eval-source-map 每一个JS语句后面都会跟一个source-map 错误代码信息和位置都能反馈
    nosources-source-map 外部 错误代码准确信息，但是没有任何源代码信息
    cheap-source-map 外部 错误代码信息和位置都有。但是源代码只精准到哪一行，并没有精确到哪一列
    cheap-module-source-map 外部 错误信息和位置都有。并且会将loader的source-map也加入
    内联速度相比较外部，内联更加快（毕竟没有生成单独的文件）
    速度快 eval>inline>cheap
    eval-cheap-source-map
    eval-source-map
    调试友好
    source-map
    cheap-module-source-map
    cheap-source-map
    结论：我们如果追求调试友好：(这也是我们开发环境最经常用的)
    eval-source-map
    我们追求速度更快：eval-cheap-module-source-map
    我们用的vue和react之类的脚手架用的就是eval-source-map
    生产环境：我们要让文件体积更小，所以不考虑所有内联方案
    调试性能最好：(开发环境我们最经常用的)
    source-map
    速度更快：
    cheap-module-source-map
    源代码全部隐藏：
    nosources-source-map
    只隐藏源代码，构建后的代码错误还是会提示：
    hidden-source-map
    */
}